//
//  NetworkInterfaceSensor.m
//  Pennyworth
//
//  Created by Chris Karr on 3/31/08.
//  Copyright 2008 Chris J. Karr. All rights reserved.
//

#import "NetworkInterfaceSensor.h"
#import "Context.h"
#import "SensorsController.h"

#define SENSOR_NAME @"Network Interfaces"

@implementation NetworkInterfaceSensor

static void linkChange (SCDynamicStoreRef store, CFArrayRef changedKeys,  void *info)
{
	if (![[SensorsController sharedController] canFire:SENSOR_NAME])
		return;

	SCDynamicStoreContext ctxt;
	ctxt.version = 0;
	ctxt.info = info;
	ctxt.retain = NULL;
	ctxt.release = NULL;
	ctxt.copyDescription = NULL;
	SCDynamicStoreRef newStore = SCDynamicStoreCreate (NULL, CFSTR ("Pennyworth"), NULL, &ctxt);

	NSArray * all = (NSArray *) SCNetworkInterfaceCopyAll ();
	
	NSEnumerator *en = [all objectEnumerator];
	SCNetworkInterfaceRef inter;
	while ((inter = (SCNetworkInterfaceRef) [en nextObject])) 
	{
		CFStringRef name = SCNetworkInterfaceGetBSDName (inter);

		NSString * linkKey = [NSString stringWithFormat:@"State:/Network/Interface/%@/Link", name];
		NSString * ipFourKey = [NSString stringWithFormat:@"State:/Network/Interface/%@/IPv4", name];
		
		CFDictionaryRef current = SCDynamicStoreCopyValue (newStore, (CFStringRef) linkKey);
		
		NSMutableDictionary * note = [NSMutableDictionary dictionary];
	
		[note setValue:[NSString stringWithFormat:@"Interface State (%@)", name] forKey:OBSERVATION_SENSOR];

		[note setValue:@"Inactive" forKey:OBSERVATION_OBSERVATION];
		
		if (current != nil)
		{
			if (CFDictionaryGetValue (current, CFSTR ("Active")) == kCFBooleanTrue)
				[note setValue:@"Active" forKey:OBSERVATION_OBSERVATION];

			CFRelease (current);
		}

		[[NSNotificationCenter defaultCenter] postNotificationName:OBSERVATION_UPDATE object:info userInfo:note];

		current = SCDynamicStoreCopyValue (newStore, (CFStringRef) ipFourKey);
		
		note = [NSMutableDictionary dictionary];
	
		[note setValue:[NSString stringWithFormat:@"Broadcast Address (%@)", name] forKey:OBSERVATION_SENSOR];
	
		if (current != nil)
		{
			NSArray * addresses = (NSArray *) CFDictionaryGetValue (current, CFSTR ("BroadcastAddresses"));

			[note setValue:[addresses lastObject] forKey:OBSERVATION_OBSERVATION];
			CFRelease (current);
		}
		else
			[note setValue:@"No Address" forKey:OBSERVATION_OBSERVATION];

		[[NSNotificationCenter defaultCenter] postNotificationName:OBSERVATION_UPDATE object:info userInfo:note];
	}
	
	[all release];
}

- (void) awakeFromNib
{
	[[SensorsController sharedController] addSensor:SENSOR_NAME];
	
	SCDynamicStoreContext ctxt;
	ctxt.version = 0;
	ctxt.info = self;
	ctxt.retain = NULL;
	ctxt.release = NULL;
	ctxt.copyDescription = NULL;
	
	interfaces = [[NSMutableArray alloc] init];
	
	NSArray * all = (NSArray *) SCNetworkInterfaceCopyAll();

	NSEnumerator * e = [all objectEnumerator];
	SCNetworkInterfaceRef inter;
	while ((inter = (SCNetworkInterfaceRef) [e nextObject])) 
	{
		CFStringRef name = SCNetworkInterfaceGetBSDName (inter);
		[interfaces addObject:[NSString stringWithFormat:@"State:/Network/Interface/%@/IPv4", name]];
		[interfaces addObject:[NSString stringWithFormat:@"State:/Network/Interface/%@/Link", name]];
	}
	
	[all release];
	
	store = SCDynamicStoreCreate (NULL, CFSTR ("Pennyworth"), linkChange, &ctxt);
	runLoop = SCDynamicStoreCreateRunLoopSource (NULL, store, 0);
	CFRunLoopAddSource (CFRunLoopGetCurrent (), runLoop, kCFRunLoopCommonModes);

	SCDynamicStoreSetNotificationKeys (store, (CFArrayRef) interfaces, NULL);
	
	[NSTimer scheduledTimerWithTimeInterval:5 target:self selector:@selector(update:) userInfo:nil repeats:NO];
}

- (void) update:(NSTimer *) theTimer
{
	linkChange (store, (CFArrayRef) interfaces, self);
}

@end
